home *** CD-ROM | disk | FTP | other *** search
- /* Wide AREA INFORMATION SERVER SOFTWARE
- No guarantees or restrictions. See the readme file for the full standard
- disclaimer.
-
- 3.26.90 Harry Morris, morris@think.com
- 4.11.90 HWM - generalized conditional includes (see c-dialect.h)
- 7/19/91 speed up substrcmp by ses@ccgr.technion.ac.il (Simon E Spero)
- */
-
- #define _C_C_util_
-
- #include "cutil.h"
- #include "panic.h"
-
- #include <string.h>
-
- #ifdef ANSI_LIKE
- #include <stdarg.h>
- #else /* ndef ANSI_LIKE */
- #include <varargs.h>
- #endif /* ndef ANSI_LIKE */
-
- #ifdef M_XENIX /* perhaps this should be in ustubs.h */
- #include <malloc.h>
- char* calloc();
- #endif /* def M_XENIX */
-
- /*----------------------------------------------------------------------*/
-
- /*#define MEMORY_ACCOUNTING*/
-
- #ifdef MEMORY_ACCOUNTING
- #undef s_checkPtr
- #define s_checkPtr(ptr) fs_checkPtr(ptr)
- static FILE* memRecord = NULL;
- static void prepMemAcct _AP((void));
- static void
- prepMemAcct()
- {
- if (memRecord == NULL)
- memRecord = s_fopen("MemoryAccounting","w");
- }
- static void flushMemAcct _AP((void));
- static void
- flushMemAcct()
- {
- fflush(memRecord);
- }
- #define tickles 0
- static char* badPtr = (char*)-1;
- static size_t badSize = -1;
- #endif /* def MEMORY_ACCOUNTING */
-
- /*----------------------------------------------------------------------*/
-
- void
- fs_checkPtr(ptr)
- void* ptr;
- /* If the ptr is NULL, give an error */
- {
- #ifdef MEMORY_ACCOUNTING
- static char** ptrs = NULL;
- long i;
- static Boolean doneSetup = false;
- if (doneSetup == false)
- {
- #ifdef THINK_C
- Debugger();
- #endif /* def THINK_C */
- doneSetup = true;
- }
- #endif /* def MEMORY_ACCOUNTING */
-
- if (ptr == NULL)
- panic("checkPtr found a NULL pointer");
-
- #ifdef MEMORY_ACCOUNTING
- /* look for specific ptr (useful when tracking un-freed memory) */
- if (ptr == badPtr) warn("checking found bad ptr");
- /* tickle a memory bug */
- if (ptrs == NULL && tickles > 0)
- ptrs = (char**)malloc((size_t)tickles * sizeof(char*));
- for (i = 0; i < tickles; i++)
- { ptrs[i] = malloc((size_t)5);
- }
- for (i = 0; i < tickles; i++)
- { free(ptrs[i]);
- }
- #endif /* def MEMORY_ACCOUNTING */
-
- }
-
- /*----------------------------------------------------------------------*/
-
- void*
- fs_malloc(size)
- size_t size;
- /* does safety checks and optional accounting */
- {
- register void* ptr = NULL;
-
- #ifdef THINK_C
- ptr = (void*)NewPtr((long)size);
- s_checkPtr(ptr);
- memset(ptr,0,(size_t)size); /* zero it */
- #else
- ptr = (void*)calloc((size_t)size,(size_t)1);
- s_checkPtr(ptr);
- #endif
-
- #ifdef MEMORY_ACCOUNTING
- /* look for specific size (useful when tracking un-freed memory) */
- if (size == badSize)
- warn("bad size in malloc");
-
- prepMemAcct();
- fprintf(memRecord,"malloced %lu bytes at %lu\n",size,ptr);
- flushMemAcct();
- #endif
-
- return(ptr);
- }
-
- /*----------------------------------------------------------------------*/
-
- void*
- fs_realloc(ptr,size)
- void* ptr;
- size_t size;
- /* does safety checks and optional accounting
- note - we don't know how big ptr's memory is, so we can't ensure
- that any new memory allocated is NULLed!
- */
- {
- register void* nptr = NULL;
-
- if (ptr == NULL) /* this is really a malloc */
- return(s_malloc(size));
-
- #ifdef THINK_C
- nptr = NewPtr(size); /* need to make a copy */
- s_checkPtr(nptr);
- BlockMove(ptr,nptr,size); /* move the old contents into it */
- DisposPtr(ptr); /* get rid of the old ones */
- #else
- nptr = (void*)realloc(ptr,size);
- s_checkPtr(ptr);
- #endif
-
- #ifdef MEMORY_ACCOUNTING
- /* look for specific size (useful when tracking un-freed memory) */
- if (size == badSize)
- warn("bad size in realloc");
-
- prepMemAcct();
- fprintf(memRecord,"realloced %lu bytes at %lu from %lu\n",size,nptr,ptr);
- flushMemAcct();
- #endif
-
- return(nptr);
- }
-
- /*----------------------------------------------------------------------*/
-
- void
- fs_free(ptr)
- void* ptr;
- /* does safety checks and optional accounting */
- {
- #ifdef MEMORY_ACCOUNTING
- prepMemAcct();
- /* note that the sizeof a pointer is always 4. If only we could find out
- how much space that pointer was pointing to. Oh well, this is a place
- holder for now
- */
- fprintf(memRecord,"freed %lu bytes at %lu\n",(size_t)sizeof(ptr),ptr);
- flushMemAcct();
-
- /* look for specific ptr (useful when tracking un-freed memory) */
- if (ptr == badPtr) warn("bad ptr in free");
- #endif
-
- if (ptr != NULL) /* some non-ansi compilers/os's cant handle freeing null */
- { /* if we knew the size of this block of memory, we could clear it - oh well */
- #ifdef THINK_C
- DisposPtr(ptr);
- #else
- free(ptr);
- #endif
- }
- }
-
- /*----------------------------------------------------------------------*/
-
- char*
- s_strdup(s)
- char* s;
-
- /* return a copy of s. This is identical to the standard library routine
- strdup(), except that it is safe. If s == NULL or malloc fails,
- appropriate action is taken.
- */
- {
- unsigned long len;
- char* copy = NULL;
-
- if (s == NULL) /* saftey check to postpone stupid errors */
- return(NULL);
-
- len = strlen(s); /* length of string - terminator */
- copy = (char*)s_malloc((size_t)(sizeof(char)*(len + 1)));
- strncpy(copy,s,len + 1);
- return(copy);
- }
-
- /*----------------------------------------------------------------------*/
-
- char*
- fs_strncat(dst,src,maxToAdd,maxTotal)
- char* dst;
- char* src;
- size_t maxToAdd;
- size_t maxTotal;
-
- /* like strncat, except the fourth argument limits the maximum total
- length of the resulting string
- */
- {
- size_t dstSize = strlen(dst);
- size_t srcSize = strlen(src);
-
- if (dstSize + srcSize < maxTotal) /* use regular old strncat */
- return(strncat(dst,src,maxToAdd));
- else
- { size_t truncateTo = maxTotal - dstSize - 1;
- char saveChar = src[truncateTo];
- char* result = NULL;
- src[truncateTo] = '\0';
- result = strncat(dst,src,maxToAdd);
- src[truncateTo] = saveChar;
- return(result);
- }
- }
-
- /*----------------------------------------------------------------------*/
-
- typedef long (longfunc) _AP((long c));
-
- char*
- strtokf(s1,isDelimiter)
- char* s1;
- longfunc *isDelimiter; /* really *isDelimiter() */
-
- /* This function is exactly like strtok, except that instead of passing a
- delimiter string, you pass a function that decides if a character is
- a delimiter or not, returning IS_DELIMITER or NOT_DELIMITER respecively.
- Note that passing a NULL delimiter function will cause the last delimiter
- to be used.
- */
- {
- static char* searchStr = NULL;
- static longfunc *delimiterFunc;
- long i;
- char* startTok = NULL;
-
- if (s1 != NULL) /* passing s1 = NULL says use the last pos */
- searchStr = s1;
-
- if (isDelimiter != NULL)
- delimiterFunc = isDelimiter;
-
- if (searchStr == NULL || searchStr[0] == '\0')
- return(NULL); /* nothing left to search */
-
- if (delimiterFunc == NULL)
- return(NULL); /* no delimiter to search with */
-
- /* find the start of the next token */
- for (i = 0; searchStr[i] != '\0'; i++)
- { if ((*delimiterFunc)((long)searchStr[i]) == NOT_DELIMITER)
- break;
- }
-
- if (searchStr[i] == '\0')
- return(NULL); /* read to end of search string */
- else
- startTok = searchStr + i; /* remember the starting point for this token*/
-
- /* find the end of the next token */
- for (; searchStr[i] != '\0'; i++)
- { if ((*delimiterFunc)((long)searchStr[i]) == IS_DELIMITER)
- break;
- }
-
- /* if the end is a delimiter (and not just the end of the search string)
- replace it with '\0', and put searchStr just beyond it, otherwise
- put searchStr at the terminator. */
- if (searchStr[i] != '\0')
- { searchStr[i] = '\0';
- searchStr = searchStr + i + 1;
- }
- else
- searchStr = searchStr + i;
-
- return(startTok);
- }
-
- /*----------------------------------------------------------------------*/
-
- #ifdef ANSI_LIKE /* use ansi varargs */
-
- long
- cprintf(print,format)
- boolean print;
- char* format;
- /* just like printf, but only prints if the first argument = 1 */
- {
- va_list ap; /* the variable arguments */
- if (print == 1)
- { long res;
- va_start(ap,format); /* init ap */
- res = vprintf(format,ap); /* print the contents */
- va_end(ap); /* free ap */
- return(res);
- }
- else
- return(0);
- }
-
- #else /* use k&r varargs */
-
- long
- cprintf(va_alist)
- va_dcl
- /* just like printf, but only prints if the first argument = 1 */
- {
- va_list ap; /* the variable arguments */
- boolean print;
- long res;
-
- va_start(ap); /* init ap */
-
- print = va_arg(ap,boolean); /* get the condition */
-
- if (print == 1)
- { char* format = va_arg(ap,char*); /* get the format */
- #ifdef BSD /* some folks can't do vfprintf */
- res = printf("%s",format); /* just print the first thing */
- #else
- res = vprintf(format,ap); /* print the contents */
- #endif
- }
- else
- res = 0;
-
- va_end(ap); /* free ap */
-
- return(res);
- }
-
-
- #endif
-
- extern char* log_file_name;
- extern FILE* logfile;
-
- /* waislog - a new and improved logging facility.
- first two arguments are important, the rest is text.
-
- arg1: priority. If priority > log_level (some global), output this
- message
-
- arg2: message code. This is the kind of message (search, retrieval, etc).
- */
-
- #ifdef ANSI_LIKE /* use ansi varargs */
-
- void
- waislog(priority, message, format)
- long priority;
- long message;
- char *format;
- /* just like printf, but prints to the logfile, with PID and time. */
- {
- va_list ap; /* the variable arguments */
- static long line = 0;
-
- if(logfile == NULL && log_file_name != NULL)
- logfile = fopen(log_file_name, "a");
-
- if(logfile) {
- va_start(ap, format);
-
- fprintf(logfile, "%d: %d: %s: %d: ", getpid(), line++, printable_time(), message);
-
- vfprintf(logfile, format,ap); /* print the contents */
- fprintf(logfile, "\n");
- fflush(logfile);
- va_end(ap); /* free ap */
- }
-
- if(logfile != NULL && logfile != stderr) {
- fclose(logfile);
- logfile = NULL;
- }
- }
-
- #ifdef old
- void
- waislog(priority, message, format)
- long priority;
- long message;
- char *format;
- /* just like printf, but prints to the logfile, with PID and time. */
- {
- va_list ap; /* the variable arguments */
- static long line = 0;
-
- if(logfile == NULL && log_file_name != NULL)
- logfile = fopen(log_file_name, "a");
-
- if(logfile) {
- va_start(ap, priority);
- message = (long)va_arg(ap, long);
-
- fprintf(logfile, "%d: %d: %s: %d: ", getpid(), line++, printable_time(), message);
-
- format = (char*)va_arg(ap, char*);
-
- vfprintf(logfile, format,ap); /* print the contents */
- fprintf(logfile, "\n");
- fflush(logfile);
- va_end(ap); /* free ap */
- }
-
- if(logfile != NULL && logfile != stderr) {
- fclose(logfile);
- logfile = NULL;
- }
- }
- #endif /*old*/
- #else /* use k&r varargs */
-
- #ifndef BSD
- void
- waislog(va_alist)
- va_dcl
- /* just like printf, but prints to the logfile, with PID and time. */
- {
- va_list ap; /* the variable arguments */
- char* format;
- static long line = 0;
- int priority, message;
-
- if(logfile == NULL && log_file_name != NULL)
- logfile = fopen(log_file_name, "a");
-
-
- if(logfile) {
- va_start(ap); /* init ap */
-
- priority = va_arg(ap, int);
- message = va_arg(ap, int);
-
- fprintf(logfile, "%d: %d: %s: %d: ", getpid(), line++, printable_time(), message);
-
- format = va_arg(ap,char*); /* get the format */
-
- vfprintf(logfile, format,ap); /* print the contents */
- fprintf(logfile, "\n");
- fflush(logfile);
- va_end(ap); /* free ap */
- }
-
- if(logfile != NULL && logfile != stderr) {
- fclose(logfile);
- logfile = NULL;
- }
- }
- #endif /* NOT BSD */
-
- #endif /* ANSI_LIKE */
-
- /*----------------------------------------------------------------------*/
-
- void
- warn(message)
- char* message;
-
- {
- #ifdef THINK_C
- Debugger();
- #else
- printf("%s\n<press return to continue>\n",message);
- getchar();
- #endif
- }
-
- /*----------------------------------------------------------------------*/
- boolean substrcmp(string1,string2)
- char *string1, *string2;
- {
- /* compares the strings up until one of then ends.
- * returns true if they are the same, false if not.
- */
- register char *a, *b;
-
- a = string1;
- b = string2;
-
- while (*a && *b)
- if(*a++ != *b++)
- return false;
- return true;
- }
-
- /*----------------------------------------------------------------------*/
-
- char *printable_time()
- {
- static char *string;
- time_t tptr;
- time(&tptr);
- string = ctime(&tptr);
- if(string){
- if(string[strlen(string)-1] == '\n')
- string[strlen(string)-1] = '\0';
- return(string+4);
- }
- else
- return("Time Unknown");
- }
-
- /*----------------------------------------------------------------------*/
-
- char char_downcase(long_ch)
- unsigned long long_ch;
- {
- unsigned char ch = long_ch & 0xFF; /* just want one byte */
- /* when ansi is the way of the world, this can be tolower */
- return (((ch >= 'A') && (ch <= 'Z')) ? (ch + 'a' -'A') : ch);
- }
-
- char *string_downcase(word)
- char *word;
- {
- long i = 0;
- while(word[i] != '\0'){
- word[i] = char_downcase((unsigned long)word[i]);
- i++;
- }
- return(word);
- }
-
- /*----------------------------------------------------------------------*/
-
-
- /* parsing arguments functions */
-
- char *next_arg(argc,argv)
- int *argc;
- char ***argv;
-
- /* Returns NULL when it is out of arguments,
- This side effects both argc and argv. argc always contains the number
- of arguments left.
- The first returned is the command name.
- */
- {
- if((*argc)-- > 0)
- return(*((*argv)++));
- else
- return(NULL);
- }
-
- /*----------------------------------------------------------------------*/
-
- char *peek_arg(argc,argv)
- int *argc;
- char ***argv;
-
- /* Returns the next argument without popping it.
- Returns NULL when it is out of arguments.
- */
- {
- if((*argc) > 0)
- return(**argv);
- else
- return(NULL);
- }
-
- /*----------------------------------------------------------------------*/
-
-
- #ifdef THINK_C
- #include <EventMgr.h>
- #undef MAX_FILE_NAME_LEN
- #ifdef WAIStation
- #include "CRetrievalApp.h"
- #endif /* def WAIStation */
- #endif /* def THINK_C */
-
- void
- beFriendly()
- /* this routine is called during time intensive operations
- on single processing machines (macs and DOS). It gives
- time to other processes
- */
- {
- #ifdef never
- #ifdef THINK_C
- EventRecord macEvent; /* an event */
-
- static RgnHandle mouseRgn = NULL; /* region for mouse moved events */
- long sleepTime; /* max time between events */
-
- #ifdef WAIStation
- gApplication->FrobWaitCursor();
- #endif /* def WAIStation */
-
- if (mouseRgn == NULL)
- mouseRgn = NewRgn(); /* do we need to set its value? */
-
- sleepTime = 5; /* arbitrary - a tech note recommends < 50 */
-
- WaitNextEvent(everyEvent,&macEvent,sleepTime,mouseRgn);
- #endif /* def THINK_C */
- #endif
- }
-
- /*----------------------------------------------------------------------*/
-